package com.hmdp.service.impl;

import com.baomidou.mybatisplus.extension.api.R;
import com.hmdp.dto.Result;
import com.hmdp.entity.SeckillVoucher;
import com.hmdp.entity.VoucherOrder;
import com.hmdp.mapper.VoucherOrderMapper;
import com.hmdp.service.ISeckillVoucherService;
import com.hmdp.service.IVoucherOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.service.IVoucherService;
import com.hmdp.utils.RedisIdWork;
import com.hmdp.utils.UserHolder;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Service
public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {

    @Autowired
    ISeckillVoucherService iSeckillVoucherService;

    @Autowired
    RedisIdWork redisIdWork;

    @Override
    public Result seckillVoucher(Long id) {
        SeckillVoucher seckillVoucher = iSeckillVoucherService.getById(id);
        // 秒杀是否开始
        if(seckillVoucher.getBeginTime().isAfter(LocalDateTime.now())){
            // 秒杀尚未开始
            return Result.fail("秒杀尚未开始");
        }
        if(seckillVoucher.getEndTime().isBefore(LocalDateTime.now())){
            // 秒杀结束
            return Result.fail("秒杀结束");
        }
        // 判断库存是否不足
        if(seckillVoucher.getStock() < 1){
            // 库存不足
            return Result.fail("库存不足");
        }
        // 一人一单
        Long userId = UserHolder.getUser().getId();
        // synchronized同步锁
        // intern作用是去字符串常量池中寻找于当前值的一样的字符串并返回
        synchronized (userId.toString().intern()){
            // 获取当前的代理对象(事物)
            IVoucherOrderService proxy = (IVoucherOrderService) AopContext.currentProxy();
            return proxy.createVoucherOrder(id);
        }
    }

    @Transactional
    public Result createVoucherOrder(Long id){
        // 一人一单
        Long userId = UserHolder.getUser().getId();
        Integer count = query().eq("user_id", userId).eq("voucher_id", id).count();
        if(count > 0){
            // 用户已经下过单了
            return Result.fail("用户已经下过单了");
        }

        // 库存-1
        // 用乐观锁：关键再用于查询之前的数据的是否被修改
        // 这里就判断stock的数据是否大于0，若大于0就表示还有库存
        boolean success = iSeckillVoucherService.update().setSql("stock = stock - 1")
                .eq("voucher_id", id).gt("stock", 0).update();
        if(!success){
            return Result.fail("库存不足");
        }
        // 保存订单
        VoucherOrder voucherOrder = new VoucherOrder();
        long id1 = redisIdWork.nextId("order");
        voucherOrder.setId(id1);
        voucherOrder.setUserId(userId);
        voucherOrder.setVoucherId(id);
        save(voucherOrder);
        return Result.ok(id1);
    }
}
